package com.ehotting.edsta.circuitDesign.gen.arguments;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ehotting.edsta.circuitDesign.bean.AllMapBean;

import com.ehotting.edsta.circuitDesign.enums.CircuitTypeEnum;
import com.ehotting.edsta.circuitDesign.enums.CodeDataTypeEnum;

import com.ehotting.edsta.circuitDesign.bean.request.RequestCodeExecute;
import com.ehotting.edsta.circuitDesign.domain.EsCircuitCodeDataTemplate;
import com.ehotting.edsta.circuitDesign.domain.EsCircuitType;
import com.ehotting.edsta.circuitDesign.exception.LoggerAnnotation;
import com.ehotting.edsta.circuitDesign.gen.ScriptLogger;
import com.ehotting.edsta.circuitDesign.gen.arguments.helper.ArgumentScriptHelper;
import com.ehotting.edsta.circuitDesign.groovy.Groovy;
import com.ehotting.edsta.circuitDesign.service.IEsCircuitCodeDataTemplateService;
import com.ehotting.edsta.circuitDesign.service.IEsCircuitTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 参数转换引擎
 */
@Service
public class ArgumentsScriptEngine {

    private Logger logger = LoggerFactory.getLogger(ArgumentsScriptEngine.class);

    @Autowired
    private ArgumentsScriptFactory argumentsScriptFactory;
    @Autowired
    private IEsCircuitCodeDataTemplateService esCircuitCodeDataTemplateService;
    @Autowired
    private ArgumentScriptHelper argumentScriptHelper;

    @Autowired
    private Groovy groovy;

    /**
     * 根据输入参数，获取所有电路类型的筛选参数
     * @param inputParam
     * @return
     */
    public AllMapBean invoke(List<EsCircuitType>  circuitTypeList, RequestCodeExecute inputParam){
        AllMapBean contextMap = new AllMapBean();
        logger.info("Start ArgumentsScriptEngine.");
        /**1、存放用户输入参数**/
        contextMap.put(CircuitTypeEnum.USER,CodeDataTypeEnum.INPUT_PARAM,inputParam.getData());
        /**2、保存配置计算参数**/
        setConfig( circuitTypeList, contextMap,  inputParam);
        logger.info("End ArgumentsScriptEngine.");

        return contextMap;

    }

    /**
     * 输入参数计算
     * @param circuitTypeList
     * @param contextMap
     * @param inputParam
     */
    private void setConfig(List<EsCircuitType>  circuitTypeList,AllMapBean contextMap, RequestCodeExecute inputParam){
        Map<Long,String> scriptMap = genMain(circuitTypeList,inputParam);
        for(EsCircuitType circuitType : circuitTypeList){
            Map<String, Object> ctx =  runMain(scriptMap.get(circuitType.getId()),inputParam,contextMap);
            contextMap.put(circuitType.getCircuitType(),CodeDataTypeEnum.INPUT_PARAM,ctx);
        }
    }


    private Map<Long,String> genMain(List<EsCircuitType>  circuitTypeList, RequestCodeExecute inputParam){
        Map<Long,String> map = new HashMap<>();
        for(EsCircuitType circuitType : circuitTypeList){
            List<EsCircuitCodeDataTemplate>  circuitCodeDataTemplateList =
                    esCircuitCodeDataTemplateService.selectByTypeAndCircuitTypeId(CodeDataTypeEnum.INPUT_PARAM,circuitType.getId());
            String methodBody = argumentsScriptFactory.genMethod(circuitType, inputParam,circuitCodeDataTemplateList);
            String callBody = argumentsScriptFactory.genCall(circuitCodeDataTemplateList, inputParam.getArgumentsList());
            String content = argumentScriptHelper.genMainMethod(methodBody,callBody,inputParam);
            map.put(circuitType.getId(),content);
        }
        return map;
    }


    private Map<String, Object> runMain(String script, RequestCodeExecute inputParam,AllMapBean contextMap){

        /**输出对象**/
        Map<String, Object> ctx = new HashMap<>();

        Object[] mainParam = genMainParam(inputParam, ctx, contextMap);

        ScriptLogger.info(JSON.toJSONString(mainParam, SerializerFeature.DisableCircularReferenceDetect));

        try {
            groovy.runGroovyScript(script, argumentScriptHelper.genMainName(), mainParam);
        }catch (Exception e){
            e.printStackTrace();
            ScriptLogger.error(e,script,mainParam);
        }
        return ctx;
    }


    private Object[] genMainParam(RequestCodeExecute inputParam, Map<String, Object> ctx,AllMapBean all){
        List<String> argumentList = inputParam.getArgumentsList();
        // 定义脚本入参对象
        Object[] objectArr = new Object[argumentList.size() + 2];
        for (int i = 0; i < argumentList.size(); i++){
            objectArr[i] = inputParam.getData().get(argumentList.get(i));
        }
        objectArr[objectArr.length - 2] = ctx;
        objectArr[objectArr.length - 1] = all;
        return objectArr;
    }

}